<?php
/**
 *  wikirenderer3 (wr3) syntax to xhtml
 *
 * @package WikiRenderer
 * @subpackage rules
 * @author Laurent Jouanneau <jouanneau@netcourrier.com>
 * @copyright 2003-2006 Laurent Jouanneau
 * @link http://wikirenderer.berlios.de
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public 2.1
 * License as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

class wr3_to_xhtml extends WikiRendererConfig {
  /**
    * @var array   liste des tags inline
   */
   var $inlinetags= array( 'wr3xhtml_strong','wr3xhtml_em','wr3xhtml_u','wr3xhtml_code','wr3xhtml_q',
    'wr3xhtml_cite','wr3xhtml_acronym','wr3xhtml_link', 'wr3xhtml_plugin',
    'wr3xhtml_anchor', 'wr3xhtml_footnote');

   var $textLineContainer = 'WikiHtmlTextLine';

   /**
   * liste des balises de type bloc reconnus par WikiRenderer.
   */
   var $bloctags = array('wr3xhtml_title', 'wr3xhtml_list','wr3xhtml_hr','wr3xhtml_bloc',
                         'wr3xhtml_blockquote','wr3xhtml_table', 'wr3xhtml_p');


   var $simpletags = array('%%%'=>'<br />');


   // la syntaxe wr3 contient la possibilité de mettre des notes de bas de page
   // celles-ci seront stockées ici, avant leur incorporation à la fin du texte.
   var $footnotes = array();
   var $footnotesId='';
   var $footnotesTemplate = '<div class="footnotes"><h4>Notes</h4>%s</div>';

    /**
    * methode invoquée avant le parsing
    */
   function onStart($texte){
        $this->footnotesId = rand(0,30000);
        $this->footnotes = array(); // on remet à zero les footnotes
        return $texte;
    }

   /**
    * methode invoquée aprés le parsing
    */
    function onParse($finalTexte){
        // on rajoute les notes de bas de pages.
        if(count($this->footnotes)){
            $footnotes = implode("\n",$this->footnotes);
            $finalTexte .= str_replace('%s', $footnotes, $this->footnotesTemplate);
        }
        return $finalTexte;
    }
}

// ===================================== déclarations des tags inlines

class wr3xhtml_strong extends WikiTagXhtml {
    var $name='strong';
    var $beginTag='**';
    var $endTag='**';
}

class wr3xhtml_em extends WikiTagXhtml {
    var $name='em';
    var $beginTag="::";
    var $endTag="::";
}

class wr3xhtml_u extends WikiTagXhtml {
    var $name='u';
    var $beginTag='__';
    var $endTag='__';
}

class wr3xhtml_code extends WikiTagXhtml {
    var $name='code';
    var $beginTag='@@';
    var $endTag='@@';
}

class wr3xhtml_q extends WikiTagXhtml {
    var $name='q';
    var $beginTag='^^';
    var $endTag='^^';
    var $attribute=array('$$','lang','cite');
    var $separators=array('|');
}

class wr3xhtml_cite extends WikiTagXhtml {
    var $name='cite';
    var $beginTag="''";
    var $endTag="''";
    var $attribute=array('$$','title');
    var $separators=array('|');
}

class wr3xhtml_acronym extends WikiTagXhtml {
    var $name='acronym';
    var $beginTag='??';
    var $endTag='??';
    var $attribute=array('$$','title');
    var $separators=array('|');
}

class wr3xhtml_anchor extends WikiTagXhtml {
    var $name='anchor';
    var $beginTag='~~';
    var $endTag='~~';
    var $attribute=array('name');
    var $separators=array('|');
    function getContent(){
        return '<a name="'.htmlspecialchars($this->wikiContentArr[0]).'"></a>';
    }
}


class wr3xhtml_link extends WikiTagXhtml {

    var $name='a';
    var $beginTag='[[';
    var $endTag=']]';
    var $separators=array('|');
    function getContent(){
        global $cfg;
        $wiki_get=$cfg["wiki_get"];
        $link=$this->wikiContentArr[0];
        $desc=isset($this->wikiContentArr[1]) ? $this->wikiContentArr[1] : "";
        //identifier ce que c'est :
        
        //un lien externe?
        $regexURL = "((http|https|ftp|mailto):\/\/[\w\.\:\@\?\&\~\%\=\+\-\/\_\;\#]+)";
        if (preg_match($regexURL,$link)) {
          if(strpos($link,'javascript:')!==false) $link='#';
          $desc = ($desc=="") ? $link : $desc;
          return "<a href=\"$link\" >".htmlspecialchars($desc).'</a>';
        }
        
        //un fichier 
        $regexMedia = "/(.jpg|.gif|.png|.swf|.mp3)$/";
        if (preg_match($regexMedia,$link,$matches)) {
            if (file_exists("media/$link")) {
                //type de fichier
                switch ($matches[1]) {
                case ".jpg":
                case ".gif":
                case ".png":
                        list($width, $height) = getimagesize("media/$link");
                        if (isset($this->wikiContentArr[1])) {
                            if (preg_match("/(\d+)x(\d+)/",$this->wikiContentArr[1],$matches))
                                list($width, $height) = getNewBoxSize($width,$height,$matches[1],$matches[2]);
                        }
                        $style="";
                        if (isset($this->wikiContentArr[2])) {
                            $style='style="float:'.$this->wikiContentArr[2].'"';
                        }
                        $alt = isset($this->wikiContentArr[3]) ? 'alt="'.$this->wikiContentArr[3].'"' : 'alt="'.$link.'"';
                        $html="<img src=\"media/$link\" height=\"$height\" width=\"$width\" $style $alt />";
                        break;
                case ".swf":
                        list($width, $height, $type, $attr) = getimagesize("media/$link");
                        if (isset($this->wikiContentArr[1])) {
                            if (preg_match("/(\d+)x(\d+)/",$this->wikiContentArr[1],$matches))
                                list($width, $height) = getNewBoxSize($width,$height,$matches[1],$matches[2]);
                        }
                        $class="";
                        if (isset($this->wikiContentArr[2])) {
                            $class="on".$this->wikiContentArr[2];
                        }
                        $html="<div class=\"flash $class\" data=\"{w:$width, h:$height, src:'media/$link'}\" ></div>";
                        break;
                case ".mp3":
                        $html="<a class=\"media\" href=\"media/$link\"></a>";
                        break;
                default:
                        $html="<!-- erreur -->";
                        break;
                }
          } else {
            //le fichier n'existe pas
            $html = "**fichier supprimé**";
          }
          return $html;
        }
        
        //sinon on considere que c'est un lien interne (page wiki)

            
        $pageName=$this->wikiContentArr[0];
        $normalizePage=normalizeStr($pageName);
        
        if (empty($this->contents[1])) {
                if (strrchr($pageName, '/')!=false)
                        $description= unNormalizeStr(substr(strrchr($pageName, '/'),1));
                else
                        $description = unNormalizeStr($pageName);
        } else {
                $description= $this->contents[1];
        }
        if (pageExists($normalizePage)) {
                //lien normal
                $html="<a href=\"index.php?$wiki_get=$normalizePage\">$description</a>";
        } elseif ($cfg['islogged']) {
                //page à éditer
                $html="<a href=\"index.php?$wiki_get=$normalizePage&do=edit\">$description?</a>";
        } else {
                //pas de lien
                $html="nolink".$description;
        }
        return $html;

    }
}


class wr3xhtml_footnote extends WikiTagXhtml {
    var $name='footnote';
    var $beginTag='$$';
    var $endTag='$$';

    function getContent(){
        $number = count($this->config->footnotes) + 1;
        $id = 'footnote-'.$this->config->footnotesId.'-'.$number;
        $this->config->footnotes[] = "<p>[<a href=\"#rev-$id\" name=\"$id\" id=\"$id\">$number</a>] ".$this->contents[0].'</p>';

        return "[<a href=\"#$id\" name=\"rev-$id\" id=\"rev-$id\">$number</a>]";
   }
}


class wr3xhtml_plugin extends WikiTagXhtml {
    var $name='plugin';
    var $beginTag='{{';
    var $endTag='}}';
    var $separators=array(':');
    function getContent(){
        $pluginName=$this->wikiContentArr[0];
        $params=empty($this->wikiContentArr[1]) ? "" : $this->wikiContentArr[1];
        if (function_exists("plugin_$pluginName"))
        {
          //function exists
          $result = call_user_func('plugin_'.$pluginName, $params);
          return $result;
        } else {
          //function does not exist
          return "plugin error";
        }
   }
}


// ===================================== déclaration des différents bloc wiki

/**
 * traite les signes de types liste
 */
class wr3xhtml_list extends WikiRendererBloc {

   var $_previousTag;
   var $_firstItem;
   var $_firstTagLen;
   var $type='list';
   var $regexp="/^\s*([#-]+)(.*)/";

   function open(){
      $this->_previousTag = $this->_detectMatch[1];
      $this->_firstTagLen = strlen($this->_previousTag);
      $this->_firstItem=true;

      if(substr($this->_previousTag,-1,1) == '#')
         return "<ol>\n";
      else
         return "<ul>\n";
   }
   function close(){
      $t=$this->_previousTag;
      $str='';

      for($i=strlen($t); $i >= $this->_firstTagLen; $i--){
          $str.=($t{$i-1}== '#'?"</li></ol>\n":"</li></ul>\n");
      }
      return $str;
   }

   function getRenderedLine(){
      $t=$this->_previousTag;
      $d=strlen($t) - strlen($this->_detectMatch[1]);
      $str='';

      if( $d > 0 ){ // on remonte d'un ou plusieurs cran dans la hierarchie...
         $l=strlen($this->_detectMatch[1]);
         for($i=strlen($t); $i>$l; $i--){
            $str.=($t{$i-1}== '#'?"</li></ol>\n":"</li></ul>\n");
         }
         $str.="</li>\n<li>";
         $this->_previousTag=substr($this->_previousTag,0,-$d); // pour �tre sur...

      }elseif( $d < 0 ){ // un niveau de plus
         $c=substr($this->_detectMatch[1],-1,1);
         $this->_previousTag.=$c;
         $str=($c == '#'?"<ol><li>":"<ul><li>");

      }else{
         $str=($this->_firstItem ? '<li>':"</li>\n<li>");
      }
      $this->_firstItem=false;
      return $str.$this->_renderInlineTag($this->_detectMatch[2]);

   }


}


/**
 * traite les signes de types table
 */
class wr3xhtml_table extends WikiRendererBloc {
   var $type='table';
   var $regexp="/^\s*\| ?(.*)/";
   var $_openTag='<table border="1">';
   var $_closeTag='</table>';

   var $_colcount=0;

   function open(){
      $this->_colcount=0;
      return $this->_openTag;
   }


   function getRenderedLine(){

      $result=explode(' | ',trim($this->_detectMatch[1]));
      $str='';
      $t='';

      if((count($result) != $this->_colcount) && ($this->_colcount!=0))
         $t='</table><table border="1">';
      $this->_colcount=count($result);

      for($i=0; $i < $this->_colcount; $i++){
         $str.='<td>'. $this->_renderInlineTag($result[$i]).'</td>';
      }
      $str=$t.'<tr>'.$str.'</tr>';

      return $str;
   }

}

/**
 * traite les signes de types hr
 */
class wr3xhtml_hr extends WikiRendererBloc {

   var $type='hr';
   var $regexp='/^\s*={4,} *$/';
   var $_closeNow=true;

   function getRenderedLine(){
      return '<hr />';
   }

}


/**
 * traite les signes de types titre
 */
class wr3xhtml_title extends WikiRendererBloc {
   var $type='title';
   var $regexp="/^\s*(\!{1,3})(.*)/";
   var $_closeNow=true;

   var $_minlevel=3;
   /**
    * indique le sens dans lequel il faut interpreter le nombre de signe de titre
    * true -> ! = titre , !! = sous titre, !!! = sous-sous-titre
    * false-> !!! = titre , !! = sous titre, ! = sous-sous-titre
    */
   var $_order=true;

   function getRenderedLine(){
      if($this->_order)
         $hx= $this->_minlevel + strlen($this->_detectMatch[1])-1;
      else
         $hx= $this->_minlevel + 3-strlen($this->_detectMatch[1]);
      return '<h'.$hx.'>'.$this->_renderInlineTag($this->_detectMatch[2]).'</h'.$hx.'>';
   }
}

/**
 * traite les signes de type paragraphe
 */
class wr3xhtml_p extends WikiRendererBloc {
   var $type='p';
   var $_openTag='<p>';
   var $_closeTag='</p>';

   function detect($string){
      if($string=='') return false;
      if(preg_match("/^\s*[\*#\-\!\| \t>;<=].*/",$string)) return false;
      $this->_detectMatch=array($string,$string);
      return true;
   }
}


/**
 * traite les signes de types pre (pour afficher du code..)*
 * * nimy 01/02/2007 00:01:20 - balise perso 
 */
class wr3xhtml_bloc extends WikiRendererBloc {

    var $type='blc';
    var $_openTag='<div class="bloc" >';
    var $_closeTag='</div>';
    var $isOpen = false;

    function getRenderedLine(){
        return $this->_renderInlineTag($this->_detectMatch);
    }

    function detect($string){
        if($this->isOpen){
            if(preg_match("/(.*)\[\/bloc\]\s*$/",$string,$m)){
                $this->_detectMatch=$m[1];
                $this->isOpen=false;
            }else{
                $this->_detectMatch=$string;
            }
            return true;

        }else{
            if(preg_match("/^\s*\[bloc:(\w*)\](.*)/",$string,$m)){
            $this->_openTag='<div class="bloc type'.$m[1].'" >';
                $this->isOpen = true;
                $this->_detectMatch=$m[2];
                return true;
            }else{
                return false;
            }
        }
    }
}

/**
 * traite les signes de type blockquote
 */
class wr3xhtml_blockquote extends WikiRendererBloc {
   var $type='bq';
   var $regexp="/^\s*(\>+)(.*)/";

   function open(){
      $this->_previousTag = $this->_detectMatch[1];
      $this->_firstTagLen = strlen($this->_previousTag);
      $this->_firstLine = true;
      return str_repeat('<blockquote>',$this->_firstTagLen).'<p>';
   }

   function close(){
      return '</p>'.str_repeat('</blockquote>',strlen($this->_previousTag));
   }


   function getRenderedLine(){

      $d=strlen($this->_previousTag) - strlen($this->_detectMatch[1]);
      $str='';

      if( $d > 0 ){ // on remonte d'un cran dans la hierarchie...
         $str='</p>'.str_repeat('</blockquote>',$d).'<p>';
         $this->_previousTag=$this->_detectMatch[1];
      }elseif( $d < 0 ){ // un niveau de plus
         $this->_previousTag=$this->_detectMatch[1];
         $str='</p>'.str_repeat('<blockquote>',-$d).'<p>';
      }else{
         if($this->_firstLine)
            $this->_firstLine=false;
         else
            $str='<br />';
      }
      return $str.$this->_renderInlineTag($this->_detectMatch[2]);
   }
}



?>
